define(function(){
	return function(jQuery){
		;( function( $, window, undefined ) {
		
			'use strict';
		
			$.CatSlider = function( options, element ) {
				this.$el = $( element );
				this._init( options );
			};
		
			$.CatSlider.prototype = {
		
				_init : function( options ) {
		
					// the categories (ul)
					this.$categories = this.$el.children( 'ul' );
					// the navigation
					this.$navcategories = this.$el.find( 'nav > a' );
					var animEndEventNames = {
						'WebkitAnimation' : 'webkitAnimationEnd',
						'OAnimation' : 'oAnimationEnd',
						'msAnimation' : 'MSAnimationEnd',
						'animation' : 'animationend'
					};
					// animation end event name
					this.animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ];
					// animations and transforms support
					this.support = Modernizr.csstransforms && Modernizr.cssanimations;
					// if currently animating
					this.isAnimating = false;
					// current category
					this.current = 0;
					var $currcat = this.$categories.eq( 0 );
					if( !this.support ) {
						this.$categories.hide();
						$currcat.show();
					}
					else {
						$currcat.addClass( 'mi-current' );
					}
					// current nav category
					this.$navcategories.eq( 0 ).addClass( 'mi-selected' );
					// initialize the events
					this._initEvents();
		
				},
				_initEvents : function() {
		
					var self = this;
					this.$navcategories.on( 'click.catslider', function() {
						self.showCategory( $( this ).index() );
						return false;
					} );
		
					// reset on window resize..
					$( window ).on( 'resize', function() {
						self.$categories.removeClass().eq( 0 ).addClass( 'mi-current' );
						self.$navcategories.eq( self.current ).removeClass( 'mi-selected' ).end().eq( 0 ).addClass( 'mi-selected' );
						self.current = 0;
					} );
		
				},
				showCategory : function( catidx ) {
		
					if( catidx === this.current || this.isAnimating ) {
						return false;
					}
					this.isAnimating = true;
					// update selected navigation
					this.$navcategories.eq( this.current ).removeClass( 'mi-selected' ).end().eq( catidx ).addClass( 'mi-selected' );
		
					var dir = catidx > this.current ? 'right' : 'left',
						toClass = dir === 'right' ? 'mi-moveToLeft' : 'mi-moveToRight',
						fromClass = dir === 'right' ? 'mi-moveFromRight' : 'mi-moveFromLeft',
						// current category
						$currcat = this.$categories.eq( this.current ),
						// new category
						$newcat = this.$categories.eq( catidx ),
						$newcatchild = $newcat.children(),
						lastEnter = dir === 'right' ? $newcatchild.length - 1 : 0,
						self = this;
		
					if( this.support ) {
		
						$currcat.removeClass().addClass( toClass );
						
						setTimeout( function() {
		
							$newcat.removeClass().addClass( fromClass );
							$newcatchild.eq( lastEnter ).on( self.animEndEventName, function() {
		
								$( this ).off( self.animEndEventName );
								$newcat.addClass( 'mi-current' );
								self.current = catidx;
								var $this = $( this );
								// solve chrome bug
								self.forceRedraw( $this.get(0) );
								self.isAnimating = false;
		
							} );
		
						}, $newcatchild.length * 90 );
		
					}
					else {
		
						$currcat.hide();
						$newcat.show();
						this.current = catidx;
						this.isAnimating = false;
		
					}
		
				},
				// based on http://stackoverflow.com/a/8840703/989439
				forceRedraw : function(element) {
					if (!element) { return; }
					var n = document.createTextNode(' '),
						position = element.style.position;
					element.appendChild(n);
					element.style.position = 'relative';
					setTimeout(function(){
						element.style.position = position;
						n.parentNode.removeChild(n);
					}, 25);
				}
		
			}
		
			$.fn.catslider = function( options ) {
				var instance = $.data( this, 'catslider' );
				if ( typeof options === 'string' ) {
					var args = Array.prototype.slice.call( arguments, 1 );
					this.each(function() {
						instance[ options ].apply( instance, args );
					});
				}
				else {
					this.each(function() {
						instance ? instance._init() : instance = $.data( this, 'catslider', new $.CatSlider( options, this ) );
					});
				}
				return instance;
			};
		
		} )( jQuery, window );
		jQuery.noConflict();
	}
})